package cn.itsource.order.service.impl;

import cn.itsource.config.RedisService;
import cn.itsource.dto.OrderSubmitDto;
import cn.itsource.dto.PayDto;
import cn.itsource.order.domain.TOrderProduct;
import cn.itsource.order.domain.TOrderProductDetail;
import cn.itsource.order.domain.UserCart;
import cn.itsource.order.mapper.OrderProductDetailMapper;
import cn.itsource.order.mapper.OrderProductMapper;
import cn.itsource.order.service.IOrderProductService;
import cn.itsource.pay.service.IAlipayInfoService;
import cn.itsource.product.domain.TProduct;
import cn.itsource.product.mapper.ProductMapper;
import cn.itsource.user.domain.TLogininfo;
import cn.itsource.utils.AjaxResult;
import cn.itsource.vo.ProductCartVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class OrderProductServiceImpl implements IOrderProductService {
    @Autowired
    private RedisService redisService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private OrderProductMapper orderProductMapper;
    @Autowired
    private OrderProductDetailMapper orderProductDetailmapper;

    //这个就是调用支付宝接口，生成并跳转到支付页面的业务代码
    @Autowired
    private IAlipayInfoService alipayInfoService;

    /*
        购物车的信息，会保存在redis中，问题：redis中如何来存储这些数据？
            key: user_id
            value:
                [{key:product_id,value:UserCart}]
            提问：
                1. 用户是否可以修改购物车中某个商品数量？
                2. 是否可以删除购物车的商品？
                3. 是否可以再次添加？

            结论： 保存在redis中时，数据会以hashmap的方式存储
     */
    @Override
    public AjaxResult putCart(Long productId, Integer count, String token) {
        //1. 先根据token查询当前登录的用户id
        TLogininfo logininfo = redisService.getKeyObjectValue(token, TLogininfo.class);
        //获取到用户的ID
        Long userId = logininfo.getLoginId();
        //2. 保存到redis
        UserCart userCart = new UserCart();
        userCart.setCount(count);
        userCart.setProductId(productId);
        userCart.setUserId(userId);
        //大key:userId; 小key:productId;value:当前保存了商品完整信息的对象
        redisTemplate.boundHashOps(userId).put(productId, userCart);
        return AjaxResult.me();
    }

    /**
     * 查询当前用户名下的购物车列表信息
     *
     * @param token
     * @return
     */
    @Override
    public List<ProductCartVo> findCartsByUserId(String token) {
        //1. 先根据token查询当前登录的用户id
        TLogininfo logininfo = redisService.getKeyObjectValue(token, TLogininfo.class);
        //获取到用户的ID
        Long userId = logininfo.getLoginId();

        //2. 从redis中取出当前用户的购物车列表信息
        BoundHashOperations hashOperations = redisTemplate.boundHashOps(userId);
        List<UserCart> values = hashOperations.values();
        //3. 根据redis中存储的服务列表的数据，查询前端需要的结果：List<ProductCartVo>
        List<ProductCartVo> list = new ArrayList<>();
        for (UserCart value : values) {
            TProduct pro = productMapper.selectByPrimaryKey(value.getProductId());
            //创建一个ProductCartVo
            ProductCartVo cartVo = new ProductCartVo();
            cartVo.setProduct(pro);
            cartVo.setCount(value.getCount());
            cartVo.setTotalMoney(pro.getSaleprice() * value.getCount());

            //添加到list
            list.add(cartVo);

        }


        return list;
    }

    @Override
    public AjaxResult submitOrder(OrderSubmitDto dto, String token) {
        TLogininfo logininfo = redisService.getKeyObjectValue(token, TLogininfo.class);
        List<String> orderSnList = new ArrayList<>();//这个来保存批量支付购物车信息的所有商品订单号
        for (Map productMap : dto.getProducts()) {//批量生成订单，即每个商品生成一个订单号
            //思路分析： 涉及的表：t_order_product 和  t_order_product_detail
            //1. 保存订单数据到t_order_product
            //首次订单生成时，以下字段是有值的
            TOrderProduct orderProduct = new TOrderProduct();
            orderProduct.setState(TOrderProduct.STATE_DAIZHIFU);
            orderProduct.setPrice(new BigDecimal(dto.getTotalMoney()));
            //生成订单号
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");//格式化时间
            String orderSn = sdf.format(new Date()) + System.currentTimeMillis();
            orderProduct.setOrderSn(orderSn);
            orderSnList.add(orderSn);//将每个商品生成的订单号保存
            //最终订单提交时间
            orderProduct.setLastConfirmTime(new Date());
            orderProduct.setProductId(Long.parseLong(productMap.get("id").toString()));
            orderProduct.setUserId(logininfo.getLoginId());
            orderProductMapper.insertSelective(orderProduct);
            //2. 保存订单数据到 t_order_product_detail
            //详情表中要保存的数据，其实就是来自于 t_product表。
            //注意：订单详情表中的数据主要目的：就是为对用户选择的服务数据进行  备份！！！
            TProduct product = productMapper.selectByPrimaryKey(productMap.get("id").toString());
            TOrderProductDetail orderProductDetail = new TOrderProductDetail();
            BeanUtils.copyProperties(product, orderProductDetail);
            orderProductDetail.setId(null);
            orderProductDetail.setSalecount(Long.parseLong(productMap.get("num").toString()));
            orderProductDetail.setOrderId(orderProduct.getId());
            orderProductDetailmapper.insertSelective(orderProductDetail);
        }
        //3. 调用 aliyun第三方支付接口，弹出支付界面
        /*
            梳理业务：
                已经有的： 调用alipayInfoService.goBuy(dto) ，是可以成功发起支付请求，并跳转到支付界面
                没有的是什么？
                    1. 支付时，订单号，不能再由goBuy()生成，它应该在创建订单时，就已经生成
                    2. 支付时，显示的商品标题，也应该在创建订单时就已经生成
                    3. 商品支付的描述信息


                 支付成功后，如何处理业务？（这个业务必须是在回调的URL对应的controller中处理）
                    1. 修改每一笔订单的 支付 状态为【已支付】
                    2. 保存一条支付记录到数据库

         */


        PayDto payDto = new PayDto();
        payDto.setSubject("购物车支付");
        payDto.setSubjectDesc("支付购物车选择所有商品");
        payDto.setMoney(dto.getTotalMoney());
        //特点：服务订单在发布时，由谁发布的？平台
        //为了和前面的业务：每个门店，都有一个属于门店自己的支付的参数信息 业务相吻合
        //解决办法：将平台的支付接口信息，也作为一个门店信息保存到表中。标注：shop_id=1，表示平台
        payDto.setShopId(1L);
        //保存批量的订单号
        //问题2：这个订单号怎么办？ 解决办法：将所有的订单号，直接拼接
        payDto.setOut_trade_no(StringUtils.join(orderSnList, ","));

//2021年6月28日：要再添加一个业务：定时器。
        // 当订单生成之后，就要立马启动一个定时任务，针对的是每一个订单，都会启动一个定时任务

        //这个是已经从支付开放平台，获取了要跳转的支付界面
        String payMsg = alipayInfoService.goBuy(payDto);
        return AjaxResult.me().setData(payMsg);
    }
}
